/* Zatok - язык программирования текстовых игр
 * (С) 2010 - 2012 Меркулов Матвей Юрьевич
 * Код лицензирован под лицензией GNU LGPL
 * Вы можете прочитать текст лицензии по адресу:
 * http://www.gnu.org/copyleft/lesser.html
 * или прочитать русский перевод по адресу:
 * http://ru.wikisource.org/wiki/GNU_Lesser_General_Public_License
 */

package base;

import base.context.CParameter;
import base.module.CModule;
import base.userfunction.CFunctionCall;
import base.value.userobject.CUserObject;
import base.value.CValue;
import java.util.LinkedList;
import parser.CParser;
import parser.CReader;

/**
 * Родительский класс для всех объектов системы
 */
public class CObject {
	public CValue GetValue() {
		Error( "Невозможно получить значение из объекта" );
		return null;
	}
	


	/**
	 * Функция инициализации объекта (только для объектов пользователя и функций).
	 */
	public void Init() {
	}



	/**
	 * Функция, преобразующая объект в булево значение.
	 * @return булево значение или выдает ошибку, если преобразование невозможно.
	 */
	public boolean ToBoolean() {
		Error( "Неверный тип объекта в операциях с логическими значениями" );
		return false;
	}



	/**
	 * Функция, преобразующая объект в целое число.
	 * @return целое число или выдает ошибку, если преобразование невозможно.
	 */
	public int ToInt() {
		Error( "Неверный тип объекта в операциях с целыми числами" );
		return 0;
	}



	/**
	 * Функция, преобразующая объект в дробное число.
	 * @return дробное число или выдает ошибку, если преобразование невозможно.
	 */
	public float ToFloat() {
		Error( "Неверный тип объекта в операциях с дробными числами" );
		return 0;
	}



	/**
	 * Функция, преобразующая объект в строку.
	 * @return строку или выдает ошибку, если преобразование невозможно.
	 */
	public String ToString() {
		Error( "Неверный тип объекта в операциях со строками" );
		return "";
	}



	/**
	 * Функция, преобразующая объект в объект пользователя.
	 * @return объект пользователя или выдает ошибку, если преобразование невозможно.
	 */
	public CUserObject ToObject() {
		Error(  "Неверный тип объекта в операциях с объектами пользователя" );
		return null;
	}

	
	
	/**
	 * Функция, преобразующая объект в массив.
	 * @return массив значений или выдает ошибку, если преобразование невозможно.
	 */
	public CValue[] ToArray(){
		Error(  "Неверный тип объекта в операциях с массивами" );
		return null;
	}



	/**
	 * Функция, преобразующая объект в список.
	 * @return список значений или выдает ошибку, если преобразование невозможно.
	 */
	public LinkedList<CValue> ToList() {
		Error(  "Неверный тип объекта в операциях со списками" );
		return null;
	}
	


	/**
	 * Функция, преобразующая объект в параметр.
	 * @return текущий объект, если он является параметром, в противном случае выдает ошибку.
	 */
	public CParameter ToParameter() {
		return null;
	}
	
	

	public CFunctionCall ToFunctionCall() {
		return null;
	}

	
	
	public CModule ToModule() {
		return null;
	}



	/**
	 * Процедура приравнивания текущего объекта к указанному объекту.
	 * @param Obj объект, к которому приравнивается текущий объект.
	 */
	public void EquateTo( CObject Obj ) {
		Error( "Объект нельзя приравнивать" );
	}



	/**
	 * Функция для парсинга строки, начинающейся с ключевого слова.
	 * @param Tokens строка, разбитая на токены
	 * @return Модуль, который должен добавится в текущий список модулей, либо null, если добавлять модуль не нужно.
	 */
	public CObject Parse( LinkedList<String> Tokens ) {
		return null;
	}



	/**
	 * Процедура парсинга модулей внутри объекта в программе.
	 * @param Modules список, куда будут добавляться модули.
	 * @param BlockName название блока, завершающего описание объекта в программе.
	 * @param EndingTokenName названия токена этого блока.
	 */
	public void ParseModules( LinkedList<CModule> Modules, String BlockName, String EndingTokenName ) {
		LinkedList<String> Tokens = new LinkedList<String>();
		String LowercaseEndingTokenName = EndingTokenName.toLowerCase();
		while (true) {
			Tokens = CParser.ReadTokens();

			if ( Tokens == null ) CParser.Error( "Неожиданный конец файла в блоке " + BlockName );

			if ( Tokens.getFirst().equals( LowercaseEndingTokenName ) ) break;

			CParser.SearchForIllegalKeywords( Tokens, EndingTokenName );

			AddModule( Modules, Tokens );
		}
	}


	/**
	 * Процедура добавления модуля в список модулей. Парсит список токенов и добавляет модуль, если функция парсинга возвратила не null;
	 * @param Modules список, в который добавляется модуль.
	 * @param Tokens строка токенов для парсинга.
	 */
	public static void AddModule( LinkedList<CModule> Modules, LinkedList<String> Tokens ) {
		CObject Obj = CParser.ParseString( Tokens );
		if( Obj != null ) {
			CModule Module = Obj.ToModule();
			if ( Module != null ) Modules.add( Module );
		}
	}



	/**
	 * Процедура вывода сообщения об ошибке.
	 * @param Message текст ошибки.
	 */
	public  void Error( String Message ){
		CGraphics.Error( Message + " в строке " + CProject.CurrentLineNumber  + " файла \"" + CReader.GetFilename( CProject.CurrentFileNumber ) + "\"" );
	}



	/**
	 * Процедура выполнения списка модулей.
	 * @param Modules список модулей.
	 */
	public static void ExecuteModulesList( LinkedList<CModule> Modules ) {
		for ( CModule Module : Modules ) {
			CProject.CurrentLineNumber = Module.LineNumber;
			CProject.CurrentFileNumber = Module.FileNumber;
			Module.Execute();
			if ( CProject.ExitStatus != CProject.EExitStatus.No ) break;
		}
	}
}
